package com.dragon.mmochat.model.map;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import com.dragon.mmochat.MmochatConstant;
import com.dragon.mmochat.model.MmochatSerial;
import com.dragon.mmochat.model.enumType.MmochatBattleOrderType;
import com.dragon.mmochat.model.enumType.MmochatMaterialType;
import com.dragon.mmochat.model.enumType.MmochatRoleType;
import com.dragon.mmochat.model.enumType.MmochatTeamConditionType;
import com.dragon.mmochat.model.enumType.MmochatWeatherType;
import com.dragon.mmochat.model.role.MmochatMonster;
import com.dragon.mmochat.model.role.MmochatNpc;
import com.dragon.mmochat.model.role.MmochatPlayer;
import com.dragon.mmochat.model.role.MmochatTempNpc;
import com.dragon.mmochat.util.MmochatUtil;

//固定不变的地图
@SuppressWarnings("unchecked")
public class MmochatMap implements Serializable {
	private static final long serialVersionUID = -5150734292150546615L;
	private static MmochatSerial tmpMapIdSerial = new MmochatSerial(-1);
	private int mapId; // 惟一地图编号
	private int mapDataId; // 地图数据ID,可重复,对应"mapDataId.m"文件
	private boolean canChangeLine = true; // 是否可以换线
	private boolean walkToBattle; // 是否为遇怪地图
	private boolean canFriendlyPk = true; // 是否允许切磋
	private boolean canWatchPk = true; // 是否允许观战
	private boolean canTransToFriend = true; // 是否允许飞到好友身边
	private boolean hasWeather = false; // 能否有天气变化
	private MmochatWeatherType curWeather = MmochatWeatherType.晴天; // 当前是否在下雨
	private long startRainTick = 0; // 开始下雨的时间
	private long rainKeepTime = 0; // 下雨持续的时间
	private MmochatTeamConditionType teamCondition = MmochatTeamConditionType.任意组队;
	private String mapName = null;
	private Map<Integer, MmochatNpc>[] npcs = new ConcurrentHashMap[MmochatConstant.maxMapLineNum];
	private Map<Integer, MmochatPlayer>[] lineRoles = new ConcurrentHashMap[MmochatConstant.maxMapLineNum];
	private List<MmochatMonster> monster = new ArrayList<MmochatMonster>(); // 此地图存在的常规怪
	private List<MmochatMapTransPoint> transPoints = new ArrayList<MmochatMapTransPoint>();// 传送点
	private List<List<Integer>> bounds = new ArrayList<List<Integer>>(); // 边界:里面的List为一行边界的数据
	private List<MmochatMapHint> hints = new ArrayList<MmochatMapHint>();
	private MmochatMapGuider mapGuiderInfo = null; // 地图守护神信息
	// 此地图允许使用的战斗指令
	private List<MmochatBattleOrderType> battleOrders = new ArrayList<MmochatBattleOrderType>();

	public MmochatMap() {
		for (int i = 0; i < MmochatConstant.maxMapLineNum; i++) {
			lineRoles[i] = new ConcurrentHashMap<Integer, MmochatPlayer>();
			npcs[i] = new ConcurrentHashMap<Integer, MmochatNpc>();
		}
	}

	// 获取新的临时地图ID(<0)
	public static int createTempMapId() {
		return tmpMapIdSerial.subAndGetSerialId();
	}

	// 如果tmpMapId对应的临时地图已经关闭,在里面的玩家将被转移到的固定地图
	public static MmochatMapTransPoint getMapWhenTempMapNotFound(int tempMapId) {
		MmochatMapTransPoint newPos = new MmochatMapTransPoint();
		// TODO
		if (tempMapId >= MmochatConstant.mapId_gangBase) {
			// 帮派地图
			// 帮派使者位置
			newPos.setTransToMapId(MmochatConstant.mapId_冀州);
			newPos.setNewMapX(369);
			newPos.setNewMapY(565);
		} else {
			switch (tempMapId) {
			case MmochatConstant.mapId_30级武道会:
			case MmochatConstant.mapId_40级武道会:
			case MmochatConstant.mapId_50级武道会:
			case MmochatConstant.mapId_60级武道会:
			case MmochatConstant.mapId_70级武道会:
			case MmochatConstant.mapId_80级武道会:
			case MmochatConstant.mapId_90级武道会:
			case MmochatConstant.mapId_100级武道会:
			case MmochatConstant.mapId_110级武道会:
			case MmochatConstant.mapId_120级武道会:
				// 武道会传送人位置
				newPos.setTransToMapId(MmochatConstant.mapId_冀州);
				newPos.setNewMapX(453);
				newPos.setNewMapY(429);
				break;
			case MmochatConstant.mapId_gangMixedBattle:
				// 帮派使者位置
				newPos.setTransToMapId(MmochatConstant.mapId_冀州);
				newPos.setNewMapX(369);
				newPos.setNewMapY(565);
				break;
			case MmochatConstant.mapId_30级个人赛:
			case MmochatConstant.mapId_40级个人赛:
			case MmochatConstant.mapId_50级个人赛:
			case MmochatConstant.mapId_60级个人赛:
			case MmochatConstant.mapId_70级个人赛:
			case MmochatConstant.mapId_80级个人赛:
			case MmochatConstant.mapId_90级个人赛:
			case MmochatConstant.mapId_100级个人赛:
			case MmochatConstant.mapId_110级个人赛:
			case MmochatConstant.mapId_120级个人赛:
				// 个人赛传送人位置
				newPos.setTransToMapId(MmochatConstant.mapId_冀州);
				newPos.setNewMapX(77);
				newPos.setNewMapY(706);
				break;
			case MmochatConstant.mapId_天下第一赛场:
				// 天下第一传送人位置
				newPos.setTransToMapId(MmochatConstant.mapId_冀州);
				newPos.setNewMapX(185);
				newPos.setNewMapY(897);
				break;
			default:
				// 新手出生地
				newPos.setTransToMapId(MmochatConstant.mapId_西岐);
				newPos.setNewMapX(550);
				newPos.setNewMapY(620);
				break;
			}
		}
		return newPos;
	}

	public void setMapId(int mapId) {
		this.mapId = mapId;
	}

	public Map<Integer, MmochatNpc>[] getNpcs() {
		return npcs;
	}

	public void setNpcs(Map<Integer, MmochatNpc>[] npcs) {
		this.npcs = npcs;
	}

	public Map<Integer, MmochatPlayer>[] getLineRoles() {
		return lineRoles;
	}

	public void setLineRoles(Map<Integer, MmochatPlayer>[] lineRoles) {
		this.lineRoles = lineRoles;
	}

	public void addRole(int line, MmochatPlayer role) {
		if (line >= MmochatConstant.maxMapLineNum) {
			return;
		}
		delRole(line, role);
		lineRoles[line].put(role.getRoleId(), role);
		role.setMapId(mapId);
		role.setLine(line);
	}

	public void delRole(int line, MmochatPlayer role) {
		if (lineRoles[line].containsKey(role.getRoleId())) {
			lineRoles[line].remove(role.getRoleId());
		}
	}

	public Map<Integer, MmochatPlayer> getLineRoleMap(int line) {
		if (line >= MmochatConstant.maxMapLineNum) {
			return null;
		}
		return lineRoles[line];
	}

	public Integer getFreeLine() {
		for (int i = 0; i < MmochatConstant.maxMapLineNum; i++) {
			if (lineRoles[i].size() < MmochatConstant.maxRoleNumPerMapLine) {
				return i;
			}
		}
		return null;
	}

	public int getAllLineRoleNum() {
		int num = 0;
		for (int i = 0; i < MmochatConstant.maxMapLineNum; i++) {
			num += lineRoles[i].size();
		}
		return num;
	}

	public void addNpc(int line, MmochatNpc npc) {
		if (line >= MmochatConstant.maxMapLineNum) {
			return;
		}
		npcs[line].put(npc.getNpcId(), npc);
	}

	public void addNpc(MmochatNpc npc) {
		for (int line = 0; line < MmochatConstant.maxMapLineNum; line++) {
			npcs[line].put(npc.getNpcId(), npc);
		}
	}

	public void delNpc(int line, MmochatNpc npc) {
		if (line >= MmochatConstant.maxMapLineNum) {
			return;
		}
		npcs[line].remove(npc.getNpcId());
	}

	public void delNpc(MmochatNpc npc) {
		for (int line = 0; line < MmochatConstant.maxMapLineNum; line++) {
			npcs[line].remove(npc.getNpcId());
		}
	}

	// 获取随机固定NPC,exceptNpcId除外
	public MmochatNpc getRandomFixedNpc(int exceptNpcId) {
		MmochatNpc theNpc = null;
		List<MmochatNpc> fixedNpcList = new ArrayList<MmochatNpc>();
		for (MmochatNpc npc : npcs[0].values()) {
			if (npc instanceof MmochatTempNpc) {
				// 临时NPC
			} else if (npc.getNpcId() != exceptNpcId) {
				// 固定NPC
				fixedNpcList.add(npc);
			}
		}
		if (fixedNpcList.size() > 0) {
			try {
				int index = MmochatUtil.getRandomValue(fixedNpcList.size());
				theNpc = fixedNpcList.get(index);
			} catch (Exception e) {
			}
		}
		return theNpc;
	}

	public Map<Integer, MmochatNpc> getLineNpcMap(int line) {
		if (line >= MmochatConstant.maxMapLineNum) {
			return null;
		}
		return npcs[line];
	}

	public MmochatNpc getLineNpc(int line, int npcId) {
		if (line >= MmochatConstant.maxMapLineNum) {
			return null;
		}
		return npcs[line].get(npcId);
	}

	public int getMapId() {
		return mapId;
	}

	public int getMapDataId() {
		return mapDataId;
	}

	public void setMapDataId(int mapDataId) {
		this.mapDataId = mapDataId;
	}

	public String getMapName() {
		return mapName;
	}

	public void setMapName(String mapName) {
		this.mapName = mapName;
	}

	public List<MmochatMonster> getMonster() {
		return monster;
	}

	public void setMonster(List<MmochatMonster> monster) {
		this.monster = monster;
	}

	public List<MmochatMapTransPoint> getTransPoints() {
		return transPoints;
	}

	public void setTransPoints(List<MmochatMapTransPoint> transPoints) {
		this.transPoints = transPoints;
	}

	public List<List<Integer>> getBounds() {
		return bounds;
	}

	public void setBounds(List<List<Integer>> bounds) {
		this.bounds = bounds;
	}

	public List<MmochatMapHint> getHints() {
		return hints;
	}

	public void setHints(List<MmochatMapHint> hints) {
		this.hints = hints;
	}

	// 随机获取一个怪
	public MmochatMonster getRandMonster() {
		if (monster.size() == 0) {
			return null;
		}
		int index = (int) (Math.random() * monster.size());
		MmochatMonster model = monster.get(index);
		if (model != null) {
			int blood = MmochatUtil.getWaveValue(model.getTotalBlood(), 5);
			int speed = MmochatUtil.getWaveValue(model.getSpeed(), 5);
			int exp = MmochatUtil.getWaveValue(model.getKillExp(), 5);
			MmochatMonster newMonster = model.getClone();
			newMonster.setTotalBlood(blood);
			newMonster.setSpeed(speed);
			newMonster.setKillExp(exp);
			return newMonster;
		}
		return null;
	}

	public boolean isHasMonster() {
		// 地府、地狱都有隐性怪
		if (mapId == MmochatConstant.mapId_地府
				|| (mapId >= MmochatConstant.mapId_地狱二层 && mapId <= MmochatConstant.mapId_地狱十层)) {
			return true;
		}
		return monster.size() > 0;
	}

	// 是否有指定类型的怪物
	public boolean hasTheMonster(MmochatRoleType roleType) {
		for (MmochatMonster m : monster) {
			if (m.getRoleType() == roleType) {
				return true;
			}
		}
		return false;
	}

	// 是否有指定类型的怪物材料
	public boolean hasTheMonsterMaterial(MmochatMaterialType mType) {
		for (MmochatMonster m : monster) {
			if (m.hasTheMaterial(mType)) {
				return true;
			}
		}
		return false;
	}

	public MmochatMapTransPoint getTransPoint(int x, int y) {
		for (MmochatMapTransPoint tran : transPoints) {
			if (tran == null) {
				continue;
			}
			int tranX = tran.getX();
			int tranY = tran.getY();
			if (Math.abs(x - tranX) < 48 && Math.abs(y - tranY) < 48) {
				return tran;
			}
		}
		return null;
	}

	public boolean isCanChangeLine() {
		return canChangeLine;
	}

	public void setCanChangeLine(boolean canChangeLine) {
		this.canChangeLine = canChangeLine;
	}

	public boolean isWalkToBattle() {
		return walkToBattle;
	}

	public void setWalkToBattle(boolean walkToBattle) {
		this.walkToBattle = walkToBattle;
	}

	public boolean isCanFriendlyPk() {
		return canFriendlyPk;
	}

	public void setCanFriendlyPk(boolean canFriendlyPk) {
		this.canFriendlyPk = canFriendlyPk;
	}

	public boolean isCanTransToFriend() {
		return canTransToFriend;
	}

	public void setCanTransToFriend(boolean canTransToFriend) {
		this.canTransToFriend = canTransToFriend;
	}

	public MmochatTeamConditionType getTeamCondition() {
		return teamCondition;
	}

	public void setTeamCondition(MmochatTeamConditionType teamCondition) {
		this.teamCondition = teamCondition;
	}

	public boolean isCanWatchPk() {
		return canWatchPk;
	}

	public void setCanWatchPk(boolean canWatchPk) {
		this.canWatchPk = canWatchPk;
	}

	public boolean isHasWeather() {
		return hasWeather;
	}

	public void setHasWeather(boolean hasWeather) {
		this.hasWeather = hasWeather;
	}

	public MmochatWeatherType getCurWeather() {
		return curWeather;
	}

	public void setCurWeather(MmochatWeatherType curWeather) {
		this.curWeather = curWeather;
	}

	public long getStartRainTick() {
		return startRainTick;
	}

	public void setStartRainTick(long startRainTick) {
		this.startRainTick = startRainTick;
	}

	public long getRainKeepTime() {
		return rainKeepTime;
	}

	public void setRainKeepTime(long rainKeepTime) {
		this.rainKeepTime = rainKeepTime;
	}

	public MmochatMapGuider getMapGuiderInfo() {
		return mapGuiderInfo;
	}

	public void setMapGuiderInfo(MmochatMapGuider mapGuiderInfo) {
		this.mapGuiderInfo = mapGuiderInfo;
	}

	public List<MmochatBattleOrderType> getBattleOrders() {
		return battleOrders;
	}

	public void setBattleOrders(List<MmochatBattleOrderType> battleOrders) {
		this.battleOrders = battleOrders;
	}

}
